package com.foreverwin.mes.core.meext;

import com.foreverwin.mes.core.utils.PropertiesUtil;
import com.foreverwin.mes.core.utils.SpringUtil;
import com.sap.me.extension.Services;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;

import javax.xml.namespace.QName;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author Ervin Chen
 * @date 2020/4/29 13:40
 */
public class MEServices {

    private static final String WSDL_PATTERN = "http://%s:%s/manufacturing-papiservices/%sWSService?wsdl";
    private static final String SERVICE_INTERFACE_PATTERN = "%s.%sInterface";

    public static <T> T create(String moduleId, String serviceName, String site) throws ClassNotFoundException {
        String activeProfile = PropertiesUtil.getString("spring.profiles.active");
        if("local".equals(activeProfile)){
            MEPapiProperties papiProperties = SpringUtil.getBean(MEPapiProperties.class);
            String wsdlUrl = String.format(WSDL_PATTERN, papiProperties.getServer(), papiProperties.getPort(), serviceName);
            String namespaceURI = PapiServiceEnum.from(moduleId, serviceName).namespaceURI;
            String className = String.format(SERVICE_INTERFACE_PATTERN, moduleId, serviceName);
            Class c = Class.forName(className);
            return (T) Proxy.newProxyInstance(c.getClassLoader(), new Class[]{c}, new Handler(site, wsdlUrl, namespaceURI, papiProperties.getUsername(), papiProperties.getPassword()));
        }else{
            return Services.getService(moduleId, serviceName, site);
        }
    }

    public static class Handler implements InvocationHandler {
        private String site = null;
        private String wsdlUrl = null;
        private String namespaceURI = null;
        private String username = null;
        private String password = null;

        Handler(String site, String wsdlUrl, String namespaceURI, String username, String password) {
            this.site = site;
            this.wsdlUrl = wsdlUrl;
            this.namespaceURI = namespaceURI;
            this.username = username;
            this.password = password;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getDeclaringClass() == Object.class) {
                return method.invoke(this, args);
            }

            JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
            Client client = dcf.createClient(this.wsdlUrl);
            client.getInInterceptors().add(new LoggingInInterceptor());
            client.getOutInterceptors().add(new LoggingInInterceptor());
            HTTPConduit http = (HTTPConduit) client.getConduit();
            AuthorizationPolicy authorizationPolicy = new AuthorizationPolicy();
            authorizationPolicy.setUserName(username);
            authorizationPolicy.setPassword(password);
            authorizationPolicy.setAuthorizationType("Basic Auth");
            http.setAuthorization(authorizationPolicy);
            QName qName = new QName(this.namespaceURI, method.getName());
            Object[] result = new Object[0];
            try {
                result = client.invoke(qName, site, null, args[0]);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result.length > 0 ? result[0] : null;
        }
    }
}
